package com.jaka.framework.core.dingding.base;

import com.alibaba.fastjson.JSON;
import com.jaka.framework.common.core.base.IHttpUtils;
import com.jaka.framework.common.core.exception.EmptyValueException;
import com.jaka.framework.common.core.exception.SignMsgFailedException;
import com.jaka.framework.common.core.exception.SignVerifyFailedException;
import com.jaka.framework.core.dingding.DingTalkAPIClientBuilder;
import com.jaka.framework.core.dingding.api.user.input.GetAccessTokenInput;
import com.jaka.framework.core.dingding.api.user.result.GetAccessTokenResult;
import com.jaka.framework.core.dingding.config.APIClientConfiguration;
import okhttp3.RequestBody;
import org.apache.commons.lang3.StringUtils;

import java.text.MessageFormat;
import java.util.Objects;

import static com.jaka.framework.core.dingding.config.APIInterfaceMapping.getSplicingInput;


/**
 * @author ：james.liu
 * @date ：Created in 2021/12/14 16:37
 * @description：
 * @version: 1.0
 */
@SuppressWarnings("all")
public class DefaultAPIActionProxy {

    private static final DefaultAPIActionProxy instance = new DefaultAPIActionProxy();

    private DefaultAPIActionProxy() {
    }

    /**
     * 描述：API接口动作代理泛型方法<br/>
     *
     * @param input         入参基类
     * @param configuration 核心配置参数
     * @param httpUtils     http请求工具
     * @param clz           返回基类
     * @param requestBody   入参Body
     * @param <I>           基类
     * @param <O>           基类
     * @return
     * @throws SignMsgFailedException    签名失败
     * @throws SignVerifyFailedException 签名校验失败
     * @throws EmptyValueException       参数校验失败
     * @throws Exception                 其他异常
     */
    public <I extends AbstractAPIInput, O extends AbstractAPIResult> O doAction(
            final I input,
            final APIClientConfiguration configuration,
            final IHttpUtils httpUtils,
            final Class<O> clz,
            final RequestBody requestBody
    ) throws SignMsgFailedException, SignVerifyFailedException, EmptyValueException, Exception {
        O r;
        String accessToken = configuration.getAccessToken();
        if (StringUtils.isEmpty(accessToken)) {
            GetAccessTokenInput getAccessTokenInput = new GetAccessTokenInput();
            getAccessTokenInput.setCmdId("gettoken");
            GetAccessTokenResult getAccessTokenResult = new DingTalkAPIClientBuilder().build().getUserClient().getAccessToken(getAccessTokenInput);
            if (Objects.isNull(getAccessTokenResult)) {
                new EmptyValueException("获取access_token无效!");
            }
            accessToken = getAccessTokenResult.getAccessToken();
            if (StringUtils.isEmpty(accessToken)) {
                new EmptyValueException("获取access_token无效!");
            }
        }
        //校验参数
        input.checkParameter();
        // 获取接口相关参数
        String send = MessageFormat.format(getSplicingInput(input.getCmdId()), accessToken);
        //发起调用
        StringBuilder sb = new StringBuilder();
        String s = sb.append(configuration.getApiUrl()).append(send).toString();
        final String responseBody = httpUtils.postStringResult(s, requestBody);
        if (StringUtils.isEmpty(responseBody)) {
            throw new EmptyValueException("responseBody is null.");
        }
        String json = responseBody;
        r = JSON.parseObject(json, clz);
        return r;

    }


    /**
     * 描述：API接口动作代理泛型方法<br/>
     *
     * @param input         入参基类
     * @param configuration 核心配置参数
     * @param httpUtils     http请求工具
     * @param clz           返回基类
     * @param requestBody   入参Body
     * @param <I>           基类
     * @param <O>           基类
     * @return
     * @throws SignMsgFailedException    签名失败
     * @throws SignVerifyFailedException 签名校验失败
     * @throws EmptyValueException       参数校验失败
     * @throws Exception                 其他异常
     */
    public <I extends AbstractAPIInput, O extends AbstractAPIResult> O doGetAction(
            final I input,
            final APIClientConfiguration configuration,
            final IHttpUtils httpUtils,
            final Class<O> clz,
            final String... splicing
    ) throws SignMsgFailedException, SignVerifyFailedException, EmptyValueException, Exception {
        O r;
        String accessToken = configuration.getAccessToken();
        if (StringUtils.isEmpty(accessToken)) {
            //校验参数
            input.checkParameter();
            GetAccessTokenInput getAccessTokenInput = new GetAccessTokenInput();
            getAccessTokenInput.setCmdId("gettoken");
            GetAccessTokenResult getAccessTokenResult = new DingTalkAPIClientBuilder().build().getUserClient().getAccessToken(getAccessTokenInput);
            if (Objects.isNull(getAccessTokenResult)) {
                new EmptyValueException("获取access_token无效!");
            }
            accessToken = getAccessTokenResult.getAccessToken();
            if (StringUtils.isEmpty(accessToken)) {
                new EmptyValueException("获取access_token无效!");
            }
        }
        //校验参数
        input.checkParameter();
        // 获取接口相关参数
        String send = MessageFormat.format(getSplicingInput(input.getCmdId()), splicing);
        //发起调用
        StringBuilder sb = new StringBuilder();
        final String responseBody = httpUtils.getStringResult(sb.append(configuration.getApiUrl()).append(send).toString());
        if (StringUtils.isEmpty(responseBody)) {
            throw new EmptyValueException("responseBody is null.");
        }
        String json = responseBody;
        r = JSON.parseObject(json, clz);
        return r;

    }

    /**
     * 描述：API接口动作代理泛型方法
     *
     * @param input         入参基类
     * @param configuration 核心配置参数
     * @param httpUtils     http请求工具
     * @param clz           返回基类
     * @param <I>           入参基类
     * @param <O>           出参基类
     * @return
     * @throws SignMsgFailedException    签名失败
     * @throws SignVerifyFailedException 签名校验失败
     * @throws EmptyValueException       参数校验失败
     * @throws Exception                 其他异常
     */
    public <I extends AbstractAPIInput, O extends AbstractAPIResult> O doAction(
            final I input,
            final APIClientConfiguration configuration,
            final IHttpUtils httpUtils,
            final Class<O> clz
    ) throws SignMsgFailedException, SignVerifyFailedException, EmptyValueException, Exception {
        O r;
        // 校验参数
        input.checkParameter();
        StringBuilder sb = new StringBuilder();
        String splicingInput = getSplicingInput(input.getCmdId());
        String send = MessageFormat.format(splicingInput, configuration.getAccessKey(), configuration.getAccessSecret());
        String s = sb.append(configuration.getApiUrl()).append(send).toString();
        String responseBody = httpUtils.getStringResult(s);
        if (StringUtils.isEmpty(responseBody)) {
            throw new EmptyValueException("responseBody is null.");
        }
        String json = responseBody;
        r = JSON.parseObject(json, clz);
        return r;
    }


    public static DefaultAPIActionProxy getInstance() {
        return instance;
    }

}
